/**
 * Copyright 2020 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.util.dtd;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;

import com.jianggujin.dbfly.util.JAssert;
import com.jianggujin.dbfly.util.JStringUtils;

public class JDTDElement implements JDTDOutput {
    private final String name;
    private Map<String, JDTDAttribute> attributes = new LinkedHashMap<>();

    private JDTDItem content;
    private String comment;

    public JDTDElement(String name) {
        this(name, null);
    }

    public JDTDElement(String name, JDTDAttribute attribute, JDTDAttribute... attributes) {
        this(name, null, attribute, attributes);
    }

    public JDTDElement(String name, String attribute, String... attributes) {
        this(name, null, attribute, attributes);
    }

    public JDTDElement(String name, JDTDItem content) {
        JAssert.notNull(name, "name不能为空");
        this.name = name;
        this.content = content;
    }

    public JDTDElement(String name, JDTDItem content, JDTDAttribute attribute, JDTDAttribute... attributes) {
        JAssert.notNull(name, "name不能为空");
        this.name = name;
        this.content = content;
        JAssert.notNull(attribute, "attribute不能为空");
        this.attributes.put(attribute.getName(), attribute);
        for (JDTDAttribute att : attributes) {
            JAssert.notNull(att, "attributes中不能包含空元素");
            this.attributes.put(att.getName(), att);
        }
    }

    public JDTDElement(String name, JDTDItem content, String attribute, String... attributes) {
        JAssert.notNull(name, "name不能为空");
        this.name = name;
        this.content = content;
        JAssert.notNull(attribute, "attribute不能为空");
        this.attributes.put(attribute, new JDTDAttribute(attribute));
        for (String attr : attributes) {
            JAssert.notNull(attr, "attributes中不能包含空元素");
            this.attributes.put(attr, new JDTDAttribute(attr));
        }
    }

    public void writeWithComment(PrintWriter out) throws IOException {
        if (JStringUtils.isNotEmpty(comment)) {
            out.print("<!-- ");
            out.print(comment);
            out.print("-->");
            out.println();
        }
        this.write(out);
    }

    @Override
    public void write(PrintWriter out) throws IOException {
        out.print("<!ELEMENT ");
        out.print(this.name);
        out.print(" ");
        if (this.content != null) {
            if (this.content instanceof JDTDContainer || this.content instanceof JDTDAny
                    || this.content instanceof JDTDEmpty) {
                this.content.write(out);
            } else {
                out.print("(");
                this.content.write(out);
                out.print(")");
            }
        } else {
            out.print("ANY");
        }
        out.println(">");

        if (this.attributes != null && !this.attributes.isEmpty()) {
            out.print("<!ATTLIST ");
            out.println(this.name);
            for (JDTDAttribute attribute : this.attributes.values()) {
                attribute.write(out);
                out.println();
            }
            out.println(">");
        }
        out.println();
    }

    public String getName() {
        return this.name;
    }

    public void setAttribute(JDTDAttribute attribute) {
        JAssert.notNull(attribute, "attribute不能为空");
        this.attributes.put(attribute.getName(), attribute);
    }

    public JDTDElement withAttribute(JDTDAttribute attribute) {
        this.setAttribute(attribute);
        return this;
    }

    public JDTDAttribute removeAttribute(String attrName) {
        JAssert.notNull(attrName, "attrName不能为空");
        JDTDAttribute attribute = this.attributes.remove(attrName);
        JAssert.notNull(attribute, JStringUtils.format("属性[{}]不存在", attrName));
        return attribute;
    }

    public void removeAllAttributes() {
        this.attributes.clear();
    }

    public JDTDAttribute getAttribute(String attrName) {
        JDTDAttribute attribute = this.attributes.get(attrName);
        JAssert.notNull(attribute, JStringUtils.format("属性[{}]不存在", attrName));
        return attribute;
    }

    public void setContent(JDTDItem content) {
        this.content = content;
    }

    public JDTDItem getContent() {
        return this.content;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public JDTDElement withComment(String comment) {
        this.setComment(comment);
        return this;
    }

}
